﻿using RRQMSocket.FileTransfer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FileTransferServerDemo
{
    public partial class Form1 : Form
    {
        private FileService fileService;
        private List<FileSocketClient> clients;
        private DataTable dataTable;
        public Form1()
        {
            InitializeComponent();
            dataTable = new DataTable();
            dataTable.TableName = "OnLineClient";
            dataTable.Columns.Add("ID", typeof(string));
            dataTable.Columns.Add("Client", typeof(FileSocketClient));
        }

        private void showMsg(string msg) 
        {
            invokeOnUI(()=> { this.msgBox.AppendText(msg + "\r\n"); });
        }

        private void syncClients()
        {
            invokeOnUI(() => {
                dataTable.Rows.Clear();
                foreach (FileSocketClient client in clients)
                    dataTable.Rows.Add(new object[] { client.IP + ":" + client.Port, client});
            });
        }

        private void invokeOnUI(Action action) 
        {
            Invoke(action);
        }

        private void startBtn_Click(object sender, EventArgs e)
        {
            if (fileService != null) 
            {
                showMsg("已啟動不要重複啟動");
                return;
            }

            int port = 7789;
            string token = "FileTransferDemo";

            if (!"".Equals(portBox.Text)) 
            {
                try {
                    port = Convert.ToInt32(portBox.Text);
                }
                catch (Exception exp) {
                    showMsg("非法Port [" + portBox.Text + "] Exception ==> " + exp.ToString());
                    return;
                }
            }

            if (!"".Equals(tokenBox.Text)) 
            {
                token = tokenBox.Text;
            }

            if (string.IsNullOrEmpty(rootpathBox.Text)) 
            {
                showMsg("please define root Path to store file");
                return;
            }

            if (!System.IO.Directory.Exists(rootpathBox.Text)) 
            {
                showMsg("the defin root path is not exist");
            }

            fileService = new FileService();
            var config = new FileServiceConfig();
            config.ListenIPHosts = new RRQMSocket.IPHost[] { new RRQMSocket.IPHost(port)};
            config.VerifyToken = token;
            config.ClearInterval = -1;
            config.RootPath = rootpathBox.Text;
            fileService.Connected += FileService_Connected;
            fileService.Disconnected += FileService_Disconnected;
            fileService.Connecting += FileService_Connecting;
            fileService.BeforeFileTransfer += FileService_BeforeFileTransfer;
            fileService.FinishedFileTransfer += FileService_FinishedFileTransfer;
            try 
            {
                dataTable.Clear();

                fileService.Setup(config);
                fileService.Start();
                clients = new List<FileSocketClient>();
                clientList.DataSource = dataTable;
                clientList.DisplayMember = "ID";
                clientList.ValueMember = "Client";
                showMsg("啟動成功 Port [" + port + "] Token [" + token + "]");
            }
            catch (Exception exp) 
            {
                fileService = null;
                showMsg("啟動失敗 ==> " + exp.ToString());
            }
        }

        private void FileService_FinishedFileTransfer(FileSocketClient client, FileTransferStatusEventArgs e)
        {
            showMsg($"fileClient {client.IP} transferTask will complete ");
            while (e.Result.ResultCode != RRQMCore.ResultCode.Success) 
            {
                Thread.Sleep(1000);
            }
            showMsg($"{DateTime.Now.ToString("yyyy-MM-dd  HH:mm:ss")} fileClient {client.IP} transferTask  {e.FileRequest.SavePath} completed ");
        }

        private void FileService_BeforeFileTransfer(FileSocketClient client, FileOperationEventArgs e)
        {
            showMsg($"{DateTime.Now.ToString("yyyy-MM-dd  HH:mm:ss")} fileClient {client.IP} attemp to transfer {e.FileRequest.SavePath}");
        }

        private void FileService_Connecting(FileSocketClient client, RRQMSocket.ClientOperationEventArgs e)
        {
            showMsg($"fileClient {client.IP} is Connecting");
        }

        private void FileService_Disconnected(FileSocketClient client, RRQMSocket.MesEventArgs e)
        {
            showMsg($"fileClient {client.IP} is disconnected ");
            invokeOnUI(() => { clients.Remove(client); });
            syncClients();
        }

        private void FileService_Connected(FileSocketClient client, RRQMSocket.MesEventArgs e)
        {
            showMsg($"fileClient {client.IP} is Connected");
            invokeOnUI(()=> {   clients.Add(client); });
            syncClients();
        }

        private void stopBtn_Click(object sender, EventArgs e)
        {
            if (fileService == null) 
            {
                showMsg("尚未啟動或已關閉");
                return;
            }

            try
            {
                fileService.Stop();
                showMsg("已停止");
                fileService = null;
                clients.Clear();
                syncClients();
            }
            catch (Exception exp) {
                showMsg("停止異常 ==> " + exp.ToString());
            }
        }

        private void pushFile(object sender, EventArgs e)
        {
            FileRequest fileRequest = new FileRequest();
            fileRequest.Overwrite = false;
            fileRequest.FileCheckerType = FileCheckerType.MD5;
            fileRequest.Flags = TransferFlags.BreakpointResume;

            FileOperator fileOperator = new FileOperator();
            
        }

        private void clearMsg(object sender, EventArgs e)
        {
            invokeOnUI( ()=> { this.msgBox.Clear(); } );
        }
    }
}
